package com.tuanzi.loan.security;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tuanzi.loan.business.entity.LoginUser;
import com.tuanzi.loan.business.entity.system.*;
import com.tuanzi.loan.business.service.system.*;

@Service
@Transactional
public class LoanUserDetailServiceImpl implements UserDetailsService {

	@Autowired
	private SystemUserService userService;
	@Autowired
	private MenuService menuService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private PartnerService partnerService;
	@Autowired
	private FunctionalPermissionService functionalPermissionService;
	@Autowired
	private DataPermissionService dataPermissionService;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		if (StringUtils.equals("SA", username)) {
			return structureSAUser();
		} else {
			return structureLoginUser(username);
		}
	}

	private LoginUser structureSAUser() {
		List<FunctionalPermission> functionalPermissions = functionalPermissionService.findAll();
		Map<String/* code */, DataPermission> dataPermissions = convertDataPermissionToMap(dataPermissionService.findAll());
		List<String> permissionCodes = functionalPermissions.parallelStream().map(FunctionalPermission::getCode).collect(Collectors.toList());
		List<String> interceptUrls = functionalPermissions.parallelStream().map(FunctionalPermission::getInterceptUrl).filter(StringUtils::isNotBlank).collect(Collectors.toList());
		List<Role> roles = roleService.findAll();
		List<Menu> menus = menuService.findAll();
		Collection<GrantedAuthority> auths = permissionCodes.parallelStream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());

		LoginUser loginUser = new LoginUser(null, "SA", "超级管理员", null, null, "SA", null, permissionCodes, dataPermissions, interceptUrls, menus, roles,
				"$2a$10$MtJ5pxoVYaowjaVdu1DpZ.m/Qexc4cMNPjEs/C5ByS6N1s9O8irJq", true, true, true, true, auths);

		return loginUser;
	}

	private LoginUser structureLoginUser(String username) {
		boolean accountNonExpired = true;
		boolean credentialsNonExpired = true;
		boolean accountNonLocked = true;
		boolean accountEnabled = true;

		SystemUser user = userService.findOneByAccount(username);

		if (user == null) {
			return null;
		}

		Collection<GrantedAuthority> auths = Lists.newArrayList();
		List<String> permissionCodes = Lists.newArrayList();
		Map<String/* code */, DataPermission> dataPermissions = Maps.newHashMap();
		List<String> interceptUrls = Lists.newArrayList();
		List<Role> roles = Lists.newArrayList();
		List<Menu> menus = Lists.newArrayList();

		Partner partner = null;

		if (user.getEnable()) {
			List<FunctionalPermission> functionalPermissions = functionalPermissionService.findAllPermissionByUserId(user.getId());
			dataPermissions = convertDataPermissionToMap(dataPermissionService.findAllPermissionByUserId(user.getId()));
			permissionCodes = functionalPermissions.parallelStream().map(FunctionalPermission::getCode).collect(Collectors.toList());
			interceptUrls = functionalPermissions.parallelStream().map(FunctionalPermission::getInterceptUrl).filter(StringUtils::isNotBlank).collect(Collectors.toList());

			auths = permissionCodes.parallelStream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());

			roles = roleService.findAllByUserId(user.getId());

			//使用默认密码用户，只展示用户设置界面，强制用户修改密码
			if(!userService.isUseDefaultPassword(user.getAccount())){
				menus = menuService.findAllByUserId(user.getId());
			}

			partner = partnerService.findOne(user.getPartnerId());
		}

		accountEnabled = user.getEnable();
		accountNonLocked = !user.getLocked();

		LoginUser loginUser = new LoginUser(user.getId(), user.getAccount(), user.getName(), user.getPhone(), user.getEmail(), user.getAccount(), partner, permissionCodes,
				dataPermissions, interceptUrls, menus, roles, user.getPwd(), accountEnabled, accountNonExpired, credentialsNonExpired, accountNonLocked, auths);

		return loginUser;
	}

	private Map<String/* code */, DataPermission> convertDataPermissionToMap(List<DataPermission> dataPermissions) {
		if (CollectionUtils.isEmpty(dataPermissions)) {
			return Maps.newHashMap();
		}

		Map<String/* code */, DataPermission> dataPermissionMap = Maps.newHashMap();
		for (DataPermission dataPermission : dataPermissions) {
			dataPermissionMap.put(dataPermission.getCode(), dataPermission);
		}

		return dataPermissionMap;
	}
}
